
// import EventElement from "./EventElement";
import $Element from "./Element";
// const ALLElementEventsMap = new WeakMap<EventElement,Map<string, Array<(event:Event)=>any>>>();
type TEventTypeMap = Map<string, Array<(event:Event)=>any>>;
const ALLElementEventsMap = new WeakMap<$Element,TEventTypeMap>();
const TargetEventMapMgrMap = new Map<TEventTypeMap,TargetEventMapMgr>();
class TargetEventMapMgr{
    private value:Map<string, Array<(event:Event)=>any>>;
    constructor(eventsMap:Map<string, Array<(event:Event)=>any>>){
        this.value = eventsMap;
    }
    get current(){
        return this.value;
    }
    getEventArray(evtName:string){
        let evtArray = this.value.get(evtName);
        if(!evtArray){
            evtArray = [];
            this.value.set(evtName, evtArray);
        }
        return evtArray;
    }
}


function getTargetEventMap(evtElement: $Element){
    let eventsMap = ALLElementEventsMap.get(evtElement);
    if(!eventsMap){
        eventsMap = new Map<string,Array<(event:Event)=>any>>();
        ALLElementEventsMap.set(evtElement,eventsMap);
    }
    return eventsMap;
}


export default class EventManage{
    private eventTarget:$Element;
    constructor(eventTarget:$Element){
        this.eventTarget = eventTarget;
    }

    addEventDelegate(evtName:string,callBack:(event:Event)=>any, currentEventTarget:HTMLElement){
        const self = this;
        const delegateTarget = new $Element(currentEventTarget);
        //存入WeakMap
        const evensMap = new TargetEventMapMgr(getTargetEventMap(delegateTarget));
        evensMap.getEventArray(evtName).push(callBack);

        //绑定事件
        if(this.eventTarget.current && this.eventTarget.current instanceof HTMLCollection){
            Array.from(this.eventTarget.current).forEach((ele:any)=>{
                ele.addEventListener(evtName,function(evt:Event){
                    if(evt.target == delegateTarget.current){
                        callBack.call(delegateTarget.current,evt);
                    }
                });
            })
        }else{
            (<HTMLElement>this.eventTarget.current).addEventListener(evtName,function(evt:Event){
                if(evt.target == delegateTarget.current){
                    callBack.call(delegateTarget.current,evt);
                }
            });
        }

        const elementEvents = ALLElementEventsMap.get(this.eventTarget) || new Map<string,Array<(event:Event)=>any>>();
        const currentEvents = elementEvents.get(evtName) || [];
        currentEvents.push(callBack);
        elementEvents.set(evtName,currentEvents);
        ALLElementEventsMap.set(this.eventTarget,elementEvents);
    }

    addEventListener(evtName:string,callBack:(event:Event)=>any){
        //存入WeakMap
        const evensMap = new TargetEventMapMgr(getTargetEventMap(this.eventTarget));
        evensMap.getEventArray(evtName).push(callBack);
        if(!this.eventTarget.current){
            throw new Error("绑定事件的原生对象不存在");
            return;
        }
        //绑定事件
        if(this.eventTarget.current && this.eventTarget.current instanceof HTMLCollection){
            Array.from(this.eventTarget.current).forEach(ele=>{
                ele.addEventListener(evtName,callBack);
            })
        }else{
            (<HTMLElement>this.eventTarget.current).addEventListener(evtName,callBack);
        }
    }

    removeEventListener(evtName:string){
        const evensMap = new TargetEventMapMgr(getTargetEventMap(this.eventTarget));

        //绑定事件
        if(this.eventTarget.current && this.eventTarget.current instanceof HTMLCollection){
            Array.from(this.eventTarget.current).forEach(ele=>{
                evensMap.getEventArray(evtName).forEach(evt=>{
                    ele.removeEventListener(evtName,evt);
                })
            })
        }else{
            evensMap.getEventArray(evtName).forEach(evt=>{
                (<HTMLElement>this.eventTarget.current).removeEventListener(evtName,evt);
            })
        }
        evensMap.getEventArray(evtName).splice(0,evensMap.getEventArray(evtName).length);
    }
    removeDOMEventListener(element:$Element){
        const eventsMap = getTargetEventMap(element);
        eventsMap.forEach((events,eventsName)=>{
            element.removeEventListener(eventsName);
        })
    }
    removeEventDelegate(evtName:string,target:$Element){
        const evensMap = new TargetEventMapMgr(getTargetEventMap(target));
        evensMap.getEventArray(evtName).splice(0,evensMap.getEventArray(evtName).length);
    }
    destroy() {
        const elementEvents = ALLElementEventsMap.get(this.eventTarget) || new Map<string,Array<(event:Event)=>any>>();
        elementEvents.forEach((events,key)=>{
            events.forEach(evt=>{
                // this.eventTarget.removeEventListener(key,evt);
            })
        })
    }
}

